package com.iflytek.autofly.setting.biz.networking;

import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.text.TextUtils;

import com.iflytek.autofly.setting.util.SpUtil;
import com.iflytek.autofly.utils.FlyLog;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * <b>Description: </b>wifi相关管理，主要是热点<br/>
 * <b>Change History:</b><br/>
 * <table border="1">
 * <tr>
 * <td><b>user</b></td>
 * <td><b>date</b></td>
 * <td><b>time</b></td>
 * <td><b>reason</b></td>
 * </tr>
 * <tr>
 * <td>JunLuan@iflytek.com</td>
 * <td>2015年5月26日</td>
 * <td>上午10:49:11</td>
 * <td>创建此文件</td>
 * </tr>
 * </table>
 *
 * @author JunLuan@iflytek.com
 */
public class FlyWifiManager {
    /**
     * Wi-Fi AP is currently being disabled. The state will change to
     * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiApState()
     */
    public static final int WIFI_AP_STATE_DISABLING = 10;
    /**
     * Wi-Fi AP is disabled.
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     */
    public static final int WIFI_AP_STATE_DISABLED = 11;
    /**
     * Wi-Fi AP is currently being enabled. The state will change to
     * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully.
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiApState()
     */
    public static final int WIFI_AP_STATE_ENABLING = 12;
    /**
     * Wi-Fi AP is enabled.
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiApState()
     */
    public static final int WIFI_AP_STATE_ENABLED = 13;
    /**
     * Wi-Fi AP is in a failed state. This state will occur when an error occurs
     * during enabling or disabling
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiApState()
     */
    public static final int WIFI_AP_STATE_FAILED = 14;
    /**
     * Broadcast intent action indicating that Wi-Fi AP has been enabled,
     * disabled, enabling, disabling, or failed.
     */
    public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
    /**
     * The lookup key for an int that indicates whether Wi-Fi AP is enabled,
     * disabled, enabling, disabling, or failed. Retrieve it with
     * {@link android.content.Intent#getIntExtra(String, int)}.
     *
     * @see #WIFI_AP_STATE_DISABLED
     * @see #WIFI_AP_STATE_DISABLING
     * @see #WIFI_AP_STATE_ENABLED
     * @see #WIFI_AP_STATE_ENABLING
     * @see #WIFI_AP_STATE_FAILED
     */
    public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
    private static final String TAG = "FlyWifiManager";
    private WifiManager mWifiManager;
    /**
     * 获取热点是否启用
     */
    private Method mIsWifiApEnabledMethod = null;
    /**
     * 获取热点设置
     */
    private Method mGetWifiApConfigurationMethod = null;
    /**
     * 启用热点
     */
    private Method mSetWifiApEnabledMethod = null;
    /**
     * 获取WIFI连接状态
     */
    private Method mGetWifiStateMethod = null;
    /**
     * 获取热点连接状态
     */
    private Method mGetWifiApStateMethod = null;

    private Context mContext = null;

    private FlyWifiManager() {

    }

    public static FlyWifiManager getInstance(Context context) {
        FlyWifiManagerInstance.INSTANCE.init(context);
        return FlyWifiManagerInstance.INSTANCE;
    }

    private void init(Context context) {
        if (mWifiManager != null) {
            return;
        }
        mContext = context;
        mWifiManager = (WifiManager) context
                .getSystemService(Context.WIFI_SERVICE);

		/* 使用反射的方法获取一些被隐藏的方法 */
        try {
            mIsWifiApEnabledMethod = mWifiManager.getClass().getMethod(
                    "isWifiApEnabled");
            mIsWifiApEnabledMethod.setAccessible(true);

            mGetWifiApConfigurationMethod = mWifiManager.getClass().getMethod(
                    "getWifiApConfiguration");
            mGetWifiApConfigurationMethod.setAccessible(true);

            mSetWifiApEnabledMethod = mWifiManager.getClass().getMethod(
                    "setWifiApEnabled", WifiConfiguration.class, boolean.class);

            mGetWifiStateMethod = mWifiManager.getClass().getMethod(
                    "getWifiState");

            mGetWifiApStateMethod = mWifiManager.getClass().getMethod(
                    "getWifiApState");

        } catch (NoSuchMethodException e) {
            mIsWifiApEnabledMethod = null;
            mGetWifiApConfigurationMethod = null;
            mSetWifiApEnabledMethod = null;
            e.printStackTrace();
        }
    }

    /**
     * setWifiEnabled:根据<i>"enable"</i>值设置wifi是否开启. <br/>
     *
     * @param enable 是否开启
     * @return 成功：true；否则：false
     */
    public boolean setWifiEnabled(boolean enable) {
        return mWifiManager != null && mWifiManager.setWifiEnabled(enable);
    }

    /**
     * isWifiEnabled:Wifi 开关是否打开. <br/>
     *
     * @return true 如果开关打开
     */
    public boolean isWifiEnabled() {
        return mWifiManager.isWifiEnabled();
    }

    /**
     * startScan:扫描wifi. <br/>
     *
     * @return 成功：true；否则：false
     */
    public boolean startScan() {
        return mWifiManager != null && mWifiManager.startScan();
    }

    /**
     * 获取WIFI状态. <br/>
     *
     * @return One of {@link WifiManager#WIFI_STATE_DISABLED},
     * {@link WifiManager#WIFI_STATE_DISABLING}, {@link WifiManager#WIFI_STATE_ENABLED},
     * {@link WifiManager#WIFI_STATE_ENABLING}, {@link WifiManager#WIFI_STATE_UNKNOWN}
     */
    public int getWifiState() {
        try {
            if (mGetWifiStateMethod != null) {
                return (Integer) mGetWifiStateMethod.invoke(mWifiManager);
            } else {
                FlyLog.e(TAG, "mGetWifiStateMethod is null");
                return WifiManager.WIFI_STATE_UNKNOWN;
            }
        } catch (Exception e) {
            FlyLog.e(TAG, e);
            return WifiManager.WIFI_STATE_UNKNOWN;
        }
    }

    /**
     * 获取热点状态. <br/>
     *
     * @return One of {@link #WIFI_AP_STATE_DISABLED},
     * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
     * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
     */
    public int getWifiApState() {
        try {
            if (mGetWifiApStateMethod != null) {
                return (Integer) mGetWifiApStateMethod.invoke(mWifiManager);
            } else {
                FlyLog.e(TAG, "mGetWifiApStateMethod is null");
                return WIFI_AP_STATE_FAILED;
            }
        } catch (Exception e) {
            FlyLog.e(TAG, e);
            return WIFI_AP_STATE_FAILED;
        }
    }

    /**
     * enableHotspot:设置公开的热点，名称为<i>"ssid"</i>. <br/>
     *
     * @param ssid ssid
     * @return 0：成功；其他：失败
     */
    public int enableHotspot(String ssid) {
        return enableHotspot(ssid, "");
    }

    /**
     * enableHotspot:设置热点，名称为<i>"ssid"</i>，密码为<i>"passwd"</i>. <br/>
     *
     * @param ssid   ssid
     * @param passwd 密码 <li>密码为“”时，不设密码，为公开的热点 <li>其他情况，采用加密
     * @return 成功：true；否则：false
     */
    public int enableHotspot(String ssid, String passwd) {
        if (mSetWifiApEnabledMethod == null) {
            return -1;
        }

        if (TextUtils.isEmpty(passwd)) {
            passwd = "";
        }

        if (getWifiApState() == FlyWifiManager.WIFI_AP_STATE_ENABLED) {
            disableAP();
        }

        if (mWifiManager == null) {
            return 0;
        }
        if (mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(false);
        }

        try {
            WifiConfiguration netConfig = new WifiConfiguration();

            netConfig.SSID = ssid;
            netConfig.preSharedKey = passwd;

            if (!TextUtils.isEmpty(passwd)) {
                netConfig.allowedAuthAlgorithms
                        .set(WifiConfiguration.AuthAlgorithm.OPEN);
                netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                netConfig.allowedKeyManagement
                        .set(WifiConfiguration.KeyMgmt.WPA_PSK);
                netConfig.allowedPairwiseCiphers
                        .set(WifiConfiguration.PairwiseCipher.CCMP);
                netConfig.allowedPairwiseCiphers
                        .set(WifiConfiguration.PairwiseCipher.TKIP);
                netConfig.allowedGroupCiphers
                        .set(WifiConfiguration.GroupCipher.CCMP);
                netConfig.allowedGroupCiphers
                        .set(WifiConfiguration.GroupCipher.TKIP);
            }

            mSetWifiApEnabledMethod.invoke(mWifiManager, netConfig, true);

        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * disableAP:禁用热点. <br/>
     *
     * @return 0：成功 其他：失败
     */
    public int disableAP() {
        int wifiApState = getWifiApState();
        if ((wifiApState == WIFI_AP_STATE_ENABLING)
                || (wifiApState == WIFI_AP_STATE_ENABLED)) {
            try {
                if (mGetWifiApConfigurationMethod == null
                        || mSetWifiApEnabledMethod == null) {
                    return -1;
                }

                WifiConfiguration config = (WifiConfiguration) mGetWifiApConfigurationMethod
                        .invoke(mWifiManager);

                mSetWifiApEnabledMethod.invoke(mWifiManager, config, false);
            } catch (IllegalArgumentException e) {
                FlyLog.e(TAG, e);
                return -1;
            } catch (IllegalAccessException e) {
                FlyLog.e(TAG, e);
                return -1;
            } catch (InvocationTargetException e) {
                FlyLog.e(TAG, e);
                return -1;
            }
        }
        return 0;
    }

    /**
     * getHotspotPasswd:获取热点密码. <br/>
     *
     * @return 密码
     */
    public String getHotspotPasswd() {
        if (mContext != null) {
            return SpUtil.getString(mContext, "AP", "passwd", "");
        }
        return "";
    }

    /**
     * setHotspotPasswd:设置热点密码. <br/>
     *
     * @param passwd 密码
     */
    public void setHotspotPasswd(String passwd) {
        SpUtil.saveString(mContext, "AP", "passwd", passwd);
    }

    /**
     * setHotspotSSID:设置热点ssid. <br/>
     *
     * @param ssid ssid
     */
    public void setHotspotSSID(String ssid) {
        SpUtil.saveString(mContext, "AP", "ssid", ssid);
    }

    public void restoreDefault() {
        clearWlanList();
    }

    public int getReflectionFieldValue(WifiConfiguration config, String name) {
        Class temp = config.getClass();
        try {
            Field field = temp.getField(name);
            return field.getInt(config);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    private void clearWlanList() {
        final List<WifiConfiguration> configs = mWifiManager
                .getConfiguredNetworks();
        if (configs != null) {
            for (WifiConfiguration config : configs) {
                if (config != null) {
                    mWifiManager.removeNetwork(config.networkId);
                }
            }
        }
        mWifiManager.saveConfiguration();
    }

    /**
     * <b>Description: </b>单体相关<br/>
     * <b>Change History:</b><br/>
     * <table border="1">
     * <tr>
     * <td><b>user</b></td>
     * <td><b>date</b></td>
     * <td><b>time</b></td>
     * <td><b>reason</b></td>
     * </tr>
     * <tr>
     * <td>JunLuan@iflytek.com</td>
     * <td>2015年5月26日</td>
     * <td>上午10:50:32</td>
     * <td>创建此文件</td>
     * </tr>
     * </table>
     *
     * @author JunLuan@iflytek.com
     */
    private static class FlyWifiManagerInstance {
        private static final FlyWifiManager INSTANCE = new FlyWifiManager();
    }
}
